package br.edu.ufcg.ga.stopcondition;

import br.edu.ufcg.ga.util.Util;

public abstract class StopCondition {

	private static double DOUBLE_UNKNOWN_VALUE = -1.0;

	protected State s;

	public StopCondition() {
		this.s = new State(DOUBLE_UNKNOWN_VALUE, 0, 0, 0);
	}

	public boolean reached(int cGeneration, double cBestFitness) {
		updateRepetitionOfBestFitness(cBestFitness);
		this.s.numGenerations++;
		return workIsDone(cGeneration, cBestFitness);
	}

	private void updateRepetitionOfBestFitness(double cBestFitness) {
		if (isEqual(this.s.lastBestFitness, DOUBLE_UNKNOWN_VALUE)) {
			this.s.lastBestFitness = cBestFitness;
		} else if (isEqual(this.s.lastBestFitness, cBestFitness)) {
			this.s.repetitionOfBestFitness++;
			this.s.cMaxRepetitionOfBestFitness = Math.max(this.s.cMaxRepetitionOfBestFitness,
					this.s.repetitionOfBestFitness);
		} else {
			this.s.repetitionOfBestFitness = 0;
			this.s.lastBestFitness = cBestFitness;
		}
	}

	protected abstract boolean workIsDone(int cGeneration, double cBestFitness);

	protected boolean isEqual(double v1, double v2) {
		return Util.isEqual(v1, v2);
	}

	public int getCMaxRepetitionOfBestFitness() {
		return this.s.cMaxRepetitionOfBestFitness;
	}

	public int getNumGenerations() {
		return this.s.numGenerations;
	}

	protected void setState(State s) {
		this.s = s;
	}

}